package com.jinlia.show.modules.base.wxapp.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jinlia.show.modules.base.constant.OrderPayStatusEnum;
import com.jinlia.show.modules.base.constant.PayForTypeEnum;
import com.jinlia.show.modules.base.model.po.PayOrderPO;
import com.jinlia.show.modules.base.model.po.UserPO;
import com.jinlia.show.modules.base.model.query.PayOrderQuery;
import com.jinlia.show.modules.base.model.vo.PayOrderVO;
import com.jinlia.show.modules.base.system.entity.MemberCard;
import com.jinlia.show.modules.base.system.entity.Order;
import com.jinlia.show.modules.base.system.service.MemberCardMapperService;
import com.jinlia.show.modules.base.system.service.OrderMapperService;
import com.jinlia.show.modules.base.wxapp.entity.MemberRechargeDiscount;
import com.jinlia.show.modules.base.wxapp.entity.PayOrder;
import com.jinlia.show.modules.base.wxapp.entity.PayOrderRecord;
import com.jinlia.show.modules.base.wxapp.entity.User;
import com.jinlia.show.modules.base.wxapp.mapper.PayOrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class PayOrderMapperService extends ServiceImpl<PayOrderMapper, PayOrder> {

    @Autowired
    private PayOrderRecordMapperService payOrderRecordMapperService;
    @Autowired
    private OrderMapperService orderMapperService;
    @Autowired
    private MemberCardMapperService memberCardMapperService;
    @Autowired
    private UserMapperService userMapperService;

    /**
     * 新增订单付款单
     *
     * @param order
     * @return
     */
    public PayOrder createByOrder(Order order) {
        PayOrder payOrder = new PayOrder();
        payOrder.setUserId(order.getUserId());
        payOrder.setPayForType(PayForTypeEnum.SALE.getValue());
        payOrder.setPayForId(order.getId());
        payOrder.setPayAmount(order.getReceivableMoney());
        payOrder.setPaidAmount(BigDecimal.ZERO);
        payOrder.setPayOrderStatus(OrderPayStatusEnum.UN_PAY.getValue());
        return payOrder;
    }

    /**
     * 通过来源单获取订单
     *
     * @return
     */
    public List<PayOrderPO> getBySource(Long sourceId) {
        List<PayOrder> list = this.lambdaQuery().eq(PayOrder::getPayForId, sourceId).list();
        List<PayOrderPO> listVO = list.stream().map(PayOrderPO::fromEntity).collect(Collectors.toList());
        for (PayOrderPO payOrderPO : listVO) {
            List<PayOrderRecord> listPayOrderRecord = payOrderRecordMapperService.lambdaQuery()
                    .eq(PayOrderRecord::getPayOrderId, payOrderPO.getId())
                    .list();
            payOrderPO.setPayOrderRecords(listPayOrderRecord);
        }
        return listVO;
    }

    /**
     * 会员充值
     *
     * @param memberCard                 会员卡
     * @param byIdMemberRechargeDiscount 充值细腻些
     * @return
     */
    public PayOrder createForMemberRecharge(MemberCard memberCard, MemberRechargeDiscount byIdMemberRechargeDiscount) {
        PayOrder payOrder = new PayOrder();
        payOrder.setPayForId(memberCard.getId());
        payOrder.setPayForType(PayForTypeEnum.MEMBER_RECHARGE.getValue());
        payOrder.setPayAmount(byIdMemberRechargeDiscount.getRechargeAmount());//充值金额
        payOrder.setPaidAmount(BigDecimal.ZERO);
        payOrder.setPayOrderStatus(OrderPayStatusEnum.UN_PAY.getValue());
        payOrder.setRechargeId(byIdMemberRechargeDiscount.getId());
        this.save(payOrder);
        return payOrder;
    }

    /**
     * 付款带查询
     *
     * @param payOrderQuery
     * @return
     */
    public Page<PayOrderVO> getPageVO(PayOrderQuery payOrderQuery) {
        Page<PayOrderVO> page = new Page<>(payOrderQuery.getCurrent(), payOrderQuery.getSize());
        Page<PayOrderVO> pageVO = this.baseMapper.getPageVO(page, payOrderQuery);
        if (!CollectionUtils.isEmpty(pageVO.getRecords())) {
            Set<Long> collect = pageVO.getRecords().stream().map(PayOrderVO::getId).collect(Collectors.toSet());
            Map<Long, List<PayOrderRecord>> idMapPayOrderRecord =
                    payOrderRecordMapperService.lambdaQuery()
                    .in(PayOrderRecord::getPayOrderId, collect)
                    .list()
                    .stream()
                    .collect(Collectors.groupingBy(PayOrderRecord::getPayOrderId));
            pageVO.getRecords().forEach(payOrderVO -> payOrderVO.setPayOrderRecords(idMapPayOrderRecord.get(payOrderVO.getId())));
        }
        //填充 payForEntity
        for (PayOrderVO record : pageVO.getRecords()) {
            if (PayForTypeEnum.SALE.getValue().equals(record.getPayForType())) {
                record.setPayForEntity(orderMapperService.getById(record.getPayForId()));
            } else if (PayForTypeEnum.MEMBER_RECHARGE.getValue().equals(record.getPayForType())) {
                record.setPayForEntity(memberCardMapperService.getById(record.getPayForId()));
            }
        }
        return pageVO;
    }

    public List<PayOrderVO> getListVO(PayOrderQuery payOrderQuery) {
        List<PayOrderVO> payOrderVOList = this.lambdaQuery()
                .between(PayOrder::getCreateTime, LocalDateTime.now().minusDays(1), LocalDateTime.now())
                .eq(PayOrder::getPayForType, PayForTypeEnum.SALE.getValue())
                .in(PayOrder::getPayOrderStatus, OrderPayStatusEnum.UN_PAY.getValue(), OrderPayStatusEnum.PART_PAY.getValue())
                .list()
                .stream()
                .map(PayOrderVO::fromEntity)
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(payOrderVOList)) {
            Map<Long, Order> idMapOrder = orderMapperService.lambdaQuery()
                    .in(Order::getId, payOrderVOList.stream().map(PayOrderVO::getPayForId).collect(Collectors.toSet()))
                    .list().stream().collect(Collectors.toMap(Order::getId, Function.identity()));
            payOrderVOList.forEach(payOrderVO -> {
                payOrderVO.setPayForEntity(idMapOrder.get(payOrderVO.getPayForId()));
                payOrderVO.setArrearsAmount(payOrderVO.getPayAmount().subtract(payOrderVO.getPaidAmount()));
            });
        }
        return payOrderVOList;
    }

    public PayOrderVO getVODetails(Long id) {
        PayOrderVO byIdPayOrder = PayOrderVO.fromEntity(this.getById(id));
        if (PayForTypeEnum.SALE.getValue().equals(byIdPayOrder.getPayForType())) {
            byIdPayOrder.setPayForEntity(orderMapperService.getById(byIdPayOrder.getPayForId()));
        }else if (PayForTypeEnum.MEMBER_RECHARGE.getValue().equals(byIdPayOrder.getPayForType())) {
            byIdPayOrder.setPayForEntity(memberCardMapperService.getById(byIdPayOrder.getPayForId()));
        }
        User byIdUser = userMapperService.getById(byIdPayOrder.getUserId());
        byIdPayOrder.setUser(UserPO.fromEntity(byIdUser));
        if (byIdUser.getMemberCardId() != null) {
            MemberCard byIdMemberCard = memberCardMapperService.getById(byIdUser.getMemberCardId());
            byIdPayOrder.getUser().setMemberCard(byIdMemberCard);
        }
        byIdPayOrder.setArrearsAmount(byIdPayOrder.getPayAmount().subtract(byIdPayOrder.getPaidAmount()));
        return byIdPayOrder;
    }
}
